﻿using System;
using Pfz.DynamicObjects.Internal;
using Pfz.Remoting.Internal;
using Pfz.Serialization;

namespace Pfz.Remoting.Serializers
{
	internal sealed class RemotingObjectSerializer:
		IItemSerializer
	{
		internal static RemotingObjectSerializer Instance = new RemotingObjectSerializer(typeof(object));

		internal RemotingObjectSerializer(Type forType)
		{
			_forType = forType;
		}

		public void Serialize(ConfigurableSerializerBase serializer, object graph)
		{
			_ReferenceOrWrapped wrapped;

			_RemotingProxy proxy = null;
			var proxy1 = graph as BaseImplementedProxy;
			if (proxy1 != null)
				proxy = proxy1._proxyObject as _RemotingProxy;

			if (proxy != null && proxy.RemotingClient == serializer.Context)
				wrapped = proxy.GetBackReference();
			else
			{
				var remotingClient = (RemotingClient)serializer.Context;
				wrapped = remotingClient._objectsUsedByTheOtherSide.GetOrWrap(graph);
			}

			serializer.InnerSerialize(wrapped);
		}

		public object Deserialize(ConfigurableSerializerBase untypedDeserializer)
		{
			var deserializer = (RemotingSerializer)untypedDeserializer;
			var result = deserializer.InnerDeserialize();

			var referenceOrWrapped = (_ReferenceOrWrapped)result;
			var remotingClient = (RemotingClient)deserializer.Context;
			result = referenceOrWrapped.GetResult(remotingClient, deserializer);
			return result;
		}

		private Type _forType;
		Type IItemSerializer.ForType
		{
			get
			{
				return _forType;
			}
		}
	}
}
